home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 3 / Cream of the Crop 3.iso / comm / wnos5src.zip / DOMSERV.C < prev    next >
Text File  |  1993-10-14  |  19KB  |  794 lines

  1. /* Domain/Name server
  2.  * Copyright 1991/2 KA9Q, PA0GRI, DK5DC and DB3FL
  3.  *
  4.  * ported to WNOS from a previous PA0GRI issue by DB3FL
  5.  *
  6.  * some code streaming and fixing done - DB3FL.91xxxx/92xxxx
  7.  * added cache from DK5DC - DB3FL.92xxxx
  8.  * fixes by WZ8Y - 9206xx
  9.  *
  10.  */
  11.  
  12. #include "global.h"
  13. #include "config.h"
  14. #include "socket.h"
  15. #include "domain.h"
  16. #include "files.h"
  17. #include "netuser.h"
  18. #include "iface.h"
  19.  
  20. #define RR_QUERY    8
  21. #define RR_INQUERY   9
  22.  
  23. Cache *cache;
  24.  
  25. static int near
  26. strxlen(char *s)
  27. {
  28.     int i = 0;
  29.  
  30.     while(*s++ != '\0') {
  31.         i++;
  32.     }
  33.     return i;
  34. }
  35.  
  36. /* Resolve an arbitrary record */
  37. static struct rr * near
  38. resolverec(char *name,int type)
  39. {
  40.     struct rr *rrp;
  41.     char *pname = NULLCHAR, *cname = NULLCHAR;
  42.     FILE *dbase;
  43.     struct rr_memory *memory;
  44.  
  45.     if(name == NULLCHAR) {
  46.         return NULLRR;
  47.     }
  48.     if(DBloaded) {
  49.         dbase = NULLFILE;
  50.     } else {
  51.         if((dbase = Fopen(Dfile,READ_TEXT,0,0)) == NULLFILE) {
  52.             return NULLRR;
  53.         }
  54.     }
  55.     memory = mxallocw(sizeof(struct rr_memory));
  56.     memory->Dname[0] = '\0';    /* initialize global area */
  57.     memory->Dttl = 3600;
  58.     memory->Dclass = 1;
  59.  
  60.     /* This code can handle a few weird cases. It works when there's
  61.      * a PTR to a CNAME to the sought record, as well as when there's a
  62.      * CNAME to a PTR to the record. But it allows only one of each kind
  63.      * of indirection to prevent infinite loops.
  64.      */
  65.     while((rrp = dfind(dbase,name,type,memory)) == NULLRR){
  66.         /* No matching record was found, let's see if it's an alias */
  67.         if(cname == NULLCHAR
  68.           && (rrp = dfind(dbase,name,TYPE_CNAME,memory)) != NULLRR){
  69.             if((cname = strxdup(rrp->rdata.name)) == NULLCHAR) {
  70.                 break;
  71.             }
  72.             name = cname;
  73.             rewind(dbase);
  74.             memory->Dname[0] = '\0'; /* initialize global area */
  75.             memory->Dttl = 3600;
  76.             memory->Dclass = 1;
  77.             memory->rrp = NULLRR;
  78.             xfree(memory->dorigin);
  79.             memory->dorigin = NULLCHAR;
  80.             free_rr(rrp);
  81.             continue;    /* Try again */
  82.         }
  83.         /* Lacking that, try a pointer entry... */
  84.         if(pname == NULLCHAR
  85.           && (rrp = dfind(dbase,name,TYPE_PTR,memory)) != NULLRR){
  86.             if((pname = strxdup(rrp->rdata.name)) == NULLCHAR) {
  87.                 break;
  88.             }
  89.             name = pname;
  90.             rewind(dbase);
  91.             memory->Dname[0] = '\0';   /* initialize global area */
  92.             memory->Dttl = 3600;
  93.             memory->Dclass = 1;
  94.             memory->rrp = NULLRR;
  95.             xfree(memory->dorigin);
  96.             memory->dorigin = NULLCHAR;
  97.             free_rr(rrp);
  98.             continue;
  99.         }
  100.         /* Nope, nothing. Give up */
  101.         break;
  102.     }
  103.     Fclose(dbase);
  104.     xfree(pname);
  105.     xfree(cname);
  106.     xfree(memory->dorigin);
  107.     xfree(memory);
  108.     return rrp;
  109. }
  110.  
  111. #ifdef XXX
  112. /* Try to figure out if we are an authority; current strategy is:
  113.  * if a domain server is defined we do not have athority
  114.  */
  115. static int near
  116. haveaa(char *name)
  117. {
  118. return Dhaveaa;
  119.  
  120.     struct rr *rrp;
  121.     int len, cnt = 0;
  122.     char *cp = name;
  123.  
  124.     /* Try to find a SOA for the whole address and by stripping off
  125.        the first part of the address. */
  126.     while(cnt < 4 && (rrp = resolverec(cp,TYPE_SOA)) == NULLRR){
  127.         if((cp = strchr(cp,'.')) == NULLCHAR)
  128.             break;
  129.         if(*(++cp) == '\0')
  130.             break;
  131.         ++cnt;
  132.     }
  133.     if(rrp != NULLRR){
  134.         len = strxlen(rrp->rdata.soa->mname);
  135.         if(rrp->rdata.soa->mname[len-1] == '.')
  136.             --len;
  137.         if(len == strxlen(Hostname) &&
  138.            strncmp(Hostname,rrp->rdata.soa->mname,len) == 0){
  139.             free_rr(rrp);
  140.             return 1;
  141.         }
  142.         free_rr(rrp);
  143.     }
  144.     return 0;
  145. }
  146. #endif
  147.  
  148. /* Main entry point for domain name -> arbitrary record resolution.
  149.  * Returns a null pointer if name is definitely not valid.
  150.  */
  151. static struct rr * near
  152. rresolve(char *name,int type,int16 fflag)
  153. {
  154.     char *buf;
  155.     int i, len, recurse = 0, auth = 0, lcount = 0;
  156.     int16 flags;
  157.     struct rr *rrp = NULLRR, *rr, *rrtmp;
  158.     struct dhdr *dhdr;
  159.     struct mbuf *bp;
  160.     struct dserver *dp = Dlist;
  161.  
  162.     while((rrp = resolverec(name,type)) == NULLRR){
  163.         if(dp == NULLDOM) {
  164.             break;
  165.         }
  166.         if(auth == 0) {
  167.             if(Dhaveaa) {
  168. #ifdef XXX
  169.             if(haveaa(name)) {       /* Quit if we are an authority */
  170. #endif
  171.                 return NULLRR;
  172.             } else {
  173.                 auth = -1;
  174.             }
  175.         }
  176.         if(uploadstatus) {
  177.             break;
  178.         }
  179.         /* Not in file, send query */
  180.         flags = DOM_DORECURSE | fflag;        /* Recursion desired */
  181.         dhdr = bld_dhdr(QUERY,QUERY,flags,NO_ERROR,name,CLASS_IN,type);
  182.         buf = mxallocw(512);                /* buf is freed by sendquery */
  183.         len = res_mkbuf(dhdr,buf,512);
  184.         free_dhdr(dhdr);           /* actualy we need to keep the question for
  185.                                    later reference when an answer comes in */
  186.         dp->queries++;
  187.  
  188.         if(sendquery(dp->address,buf,len,&bp,dp->timeout) > 0) {
  189.             dhdr = mxallocw(sizeof(struct dhdr));
  190.             ntohdomain(dhdr,&bp);
  191.             dp->responses++;
  192.             proc_answer(dhdr,dp,NULLFILE);
  193.  
  194.             if(dhdr->rcode != NO_ERROR) {
  195.                 break;
  196.             } else {
  197.                 for(i = 0; i < dhdr->ancount; i++){
  198.                     rrp = copy_rr(dhdr->ans[i]);
  199.  
  200.                     if(strnicmp(rrp->name,name,strxlen(name)) != 0) {
  201.                         continue;
  202.                     }
  203.                     /* Got one */
  204.                     switch(rrp->type) {
  205.                     case TYPE_CNAME:
  206.                         /* Change the query name to the
  207.                          * cname and go back again
  208.                          */
  209.                         if(++recurse == MAXCNAME) {
  210.                             /* too many recursions */
  211.                             break;
  212.                         }
  213.                         xfree(name);
  214.                         name = strxdup(rrp->rdata.name);
  215.  
  216.                         /* rescan the responces */
  217.                         i = -1;
  218.                         continue;
  219.                     }
  220.                     break;
  221.                 }
  222.             }
  223.             free_dhdr(dhdr);
  224.             break;
  225.         }
  226.         if(errno == EABORT) {
  227.             return NULLRR;
  228.         }
  229.         /* Timeout; back off this one and try another server */
  230.         dp->timeout += 5000;
  231.         dp->missers++;
  232.  
  233.         if((dp = dp->next) == NULLDOM) {
  234.             break;
  235.         }
  236.         if(++lcount > Dretries) {
  237.             return NULLRR;
  238.         }
  239.     }
  240.     rr = rrp;                         /* Remove any NULL records */
  241.  
  242.     while(rr != NULLRR && rr->rdlength == 0){
  243.         rrp = rr->next;
  244.         rr->next = NULLRR;
  245.         free_rr(rr);
  246.         rr = rrp;
  247.     }
  248.     while(rr != NULLRR && rr->next != NULLRR){
  249.         if(rr->next->rdlength == 0) {
  250.             rrtmp = rr->next->next;
  251.             rr->next->next = NULLRR;
  252.             free_rr(rr->next);
  253.             rr->next = rrtmp;
  254.         } else {
  255.             rr = rr->next;
  256.         }
  257.     }
  258.     return rrp;
  259. }
  260.  
  261. /*----------------------------------------------------------------------*
  262. *retrieve the next useable entry in cache                               *
  263. *-----------------------------------------------------------------------*/
  264. static Cache * near
  265. getentry(void)
  266. {
  267. Cache *ocap, *cap = cache;
  268. int i;
  269. time_t ti;
  270.  
  271.    /*-------------------------------------------------------------------*
  272.    * scan cache for an useable entry. This might be a free entry..      *
  273.    * cap->ti == 0 or the oldest entry in Cache                          *
  274.    *--------------------------------------------------------------------*/
  275.    time(&ti);
  276.  
  277.    for (i = 0; i < Dcache_size; i++)   {
  278.       if (cap->ti == 0) {
  279.          return(cap);
  280.       }
  281.       if (ti >= cap->ti)   {
  282.          ti = cap->ti;
  283.          ocap = cap;
  284.       }
  285.       cap++;
  286.    }
  287.    return(ocap);
  288. }
  289.  
  290. /*----------------------------------------------------------------------*
  291. * put an entry into the cache for later access                          *
  292. *-----------------------------------------------------------------------*/
  293. static Cache * near
  294. putcache(char *name,char *host,int32 addr,Rtype type,Ctype ctype)
  295. {
  296.    /*-------------------------------------------------------------------*
  297.    * Found it, put in cache                                             *
  298.    *--------------------------------------------------------------------*/
  299.    Cache *cap = getentry();
  300.  
  301.    semwait(&Cwrite,1);                 /* -serialize Cache access      */
  302.    /*-------------------------------------------------------------------*
  303.    * make correct entries for valid and invalid entries                 *
  304.    *--------------------------------------------------------------------*/
  305.    if (type == Address && ctype == Found)  {          /* via resolve_a()*/
  306.       sprintf(cap->name,"%.39s",strtok(name,"\t "));
  307.    } else if (ctype == Found) {            /* found in file                */
  308.       sprintf(cap->name,"%.39s",host);
  309.    }
  310.    if (type == Name && ctype == Missing)  {
  311.       cap->address = 0;
  312.       sprintf(cap->name,"%.39s",host);
  313.    } else {
  314.       cap->address = (ctype != Found) ? 0 : addr;
  315.    }
  316.    cap->type = ctype;
  317.    cap->ti = time(NULL);
  318.    semrel(&Cwrite);
  319.    return cap;
  320. }
  321.  
  322. /*----------------------------------------------------------------------*
  323. *  Perform a cache search.
  324. *-----------------------------------------------------------------------*/
  325. static Cache * near
  326. cache_search(char *name,Rtype type)
  327. {
  328. int i;
  329. char *cp;
  330. Cache *cap = cache;
  331.  
  332.    for (i = 0; i < Dcache_size; i++) {
  333.       if(i == Dcache_size) {
  334.          break;
  335.       }
  336.       if(cap->ti == 0) {
  337.          continue;
  338.       }
  339.       if(type == Name) {
  340.          if(cap->name[0] != '\0') {
  341.             if(strchr(name,'.') == NULLCHAR) {
  342.                 if((cp = strchr(cap->name,'.')) != NULLCHAR) {
  343.                     *cp = '\0';
  344.                 }
  345.                 if(stricmp(cap->name,name) == 0) {
  346.                     *cp = '.';
  347.                     return cap;
  348.                 }
  349.                 *cp = '.';
  350.             } else if(strnicmp(cap->name,name,(strxlen(name) - 1)) == 0) {
  351.                 return cap;
  352.             }
  353.          }
  354.       } else {
  355.          if(cap->address != 0 && cap->address == aton(name)) {
  356.             return cap;
  357.          }
  358.       }
  359.       cap++;
  360.    }
  361.    return(0);
  362. }
  363.  
  364. /* Main entry point for domain name -> address resolution.
  365.  * Returns 0 if name is definitely not valid.
  366.  */
  367. int32
  368. resolve(char *name)
  369. {
  370.     char *sname;
  371.     int state = Found;
  372.     int32 addr = 0;
  373.     struct rr *arrp = NULLRR;
  374.     Cache *cap;
  375.  
  376.     if(*name == '[') {
  377.         return aton(name + 1);
  378.     }
  379.     if(isaddr(name)) {
  380.         return aton(name);
  381.     }
  382.     if((cap = cache_search(name,Name)) != 0) {
  383.         return (cap->type == Found) ? cap->address : 0;
  384.     }
  385.     sname = strxdup(name);
  386.  
  387.     if((arrp = rresolve(sname,TYPE_A,DOM_CANRECURSE)) != NULLRR) {
  388.         if(arrp->rdlength == 4) {
  389.             addr = arrp->rdata.addr;
  390.             xfree(sname);
  391.             sname = strxdup(arrp->name);
  392.         }
  393.     }
  394.     if(addr == 0) {
  395.         state = Missing;
  396.     }
  397.     if(cap == 0) {
  398.         putcache(NULLCHAR,sname,addr,Name,state);
  399.     }
  400.     xfree(sname);
  401.     free_rr(arrp);
  402.     return addr;
  403. }
  404.  
  405. /* entry point for address -> domain name resolution.
  406.  * Returns NULLCHAR if address is not found.
  407.  */
  408. char *
  409. resolve_a(int32 ip_address,int shorten)
  410. {
  411.     static char pname[80];
  412.     Cache *cap;
  413.  
  414.     if(ip_address == 0) {
  415.         return NULLCHAR;
  416.     }
  417.     sprintf(pname,"%u.%u.%u.%u",
  418.         hibyte(hiword(ip_address)),lobyte(hiword(ip_address)),
  419.         hibyte(loword(ip_address)),lobyte(loword(ip_address)));
  420.  
  421.     if((cap = cache_search(pname,Address)) != 0 && cap->type == Found) {
  422.         if(cap->name[strxlen(cap->name) - 1] != '.') {
  423.             if(shorten) {
  424.                 return cap->name;
  425.             } else if (Dsuffix) {
  426.                 sprintf(pname,"%s.%s",cap->name,Dsuffix);
  427.                 return pname;
  428.             }
  429.         } else {
  430.             if(!shorten) {
  431.                 return cap->name;
  432.             }
  433.             if(Dsuffix) {
  434.                 char *j;
  435.  
  436.                 strcpy(pname,cap->name);
  437.                 j = strstr(pname,Dsuffix);
  438.  
  439.                 if (j > pname && *(--j) == '.') {
  440.                     *j = '\0';
  441.                 } else {
  442.                     pname[strxlen(pname)-1] = '\0';
  443.                 }
  444.                 return pname;
  445.             }
  446.         }
  447.     }
  448.     return NULLCHAR;
  449.  
  450. #ifdef notdef
  451.  
  452.     struct rr *rrp, *irrp, *prrp;
  453.  
  454.     sprintf( pname, "%u.%u.%u.%u%s",
  455.             lobyte(loword(ip_address)),
  456.             hibyte(loword(ip_address)),
  457.             lobyte(hiword(ip_address)),
  458.             hibyte(hiword(ip_address)),
  459.             shorten ? "" : ".IN-ADDR.ARPA." );
  460.  
  461.     irrp = make_rr(RR_INQUERY,NULLCHAR,CLASS_IN,TYPE_A,0,4,&ip_address);
  462.     prrp = make_rr(RR_QUERY,pname,CLASS_IN,TYPE_PTR,0,0,NULL);
  463.  
  464.     irrp->next = prrp;    /* make list to speed search */
  465.  
  466.     for(dname = NULLCHAR; dname == NULLCHAR;){
  467.         if((rrp=dcache_search(irrp)) == NULLRR
  468.         && (rrp=dfile_search(irrp)) == NULLRR
  469.         && (rrp=dns_query(prrp,1)) == NULLRR)
  470.             break;
  471.         if(rrp->rdlength == 0)
  472.             break;
  473.         switch(rrp->type){
  474.         case TYPE_A:
  475.             dname = strxdup(rrp->name);
  476.             break;
  477.         case TYPE_PTR:
  478.             dname = strxdup(rrp->rdata.name);
  479.             break;
  480.         default:
  481.             free_rr(rrp);
  482.         }
  483.     }
  484.     free_rr(irrp);
  485.     free_rr(prrp);
  486.     free_rr(rrp);
  487.     return dname;
  488. #endif
  489. }
  490.  
  491. /* Main entry point for M* record lookup.
  492.  * Returns NULLCHAR if name is currently unresolvable.
  493.  */
  494. char *
  495. resolve_mailb(char *name)
  496. {
  497.     struct rr *rrp, *arrp;
  498.     char *sname, *tmp, *cp;
  499.     int32 addr = 0;
  500.     int16 pref = MAXINT16;
  501.  
  502.     if(name == NULLCHAR) {
  503.         return NULLCHAR;
  504.     }
  505.     if(isaddr(name)) {
  506.         if((sname = resolve_a(aton(name),FALSE)) == NULLCHAR) {
  507.             return NULLCHAR;
  508.         }
  509.     } else {
  510.         sname = mxallocw(strxlen(name) + 2);
  511.         sprintf(sname,"%s.",name);
  512.     }
  513.     cp = sname;
  514.  
  515.     while(1){
  516.         rrp = arrp = rresolve(sname,TYPE_MX,DOM_CANRECURSE);
  517.  
  518.         /* Search this list of rr's for an MX record */
  519.         while(rrp != NULLRR) {
  520.             if(rrp->rdlength > 0 && rrp->rdata.mx.pref <= pref
  521.               && (addr = resolve(rrp->rdata.mx.exch)) != 0L) {
  522.                 pref = rrp->rdata.mx.pref;
  523.             }
  524.             rrp = rrp->next;
  525.         }
  526.         free_rr(arrp);
  527.  
  528.         if(addr != 0) {
  529.             break;
  530.         }
  531.         /* Compose wild card one level up */
  532.         if((cp = strchr(cp,'.')) == NULLCHAR) {
  533.             break;
  534.         }
  535.         tmp = mxallocw(strxlen(cp)+2);
  536.         sprintf(tmp,"*%s",cp);        /* wildcard expansion */
  537.         xfree(sname);
  538.         sname = tmp;
  539.         cp = sname + 2;
  540.     }
  541.     if(Dsuffix != NULLCHAR && addr != 0) {
  542.         if(!strstr(sname,Dsuffix)) {
  543.             char cp1[2];
  544.             tmp = mxallocw(strxlen(sname) + strxlen(Dsuffix) + 2);
  545.  
  546.             if(sname[strxlen(sname) - 1] != '.') {
  547.                 strcpy(cp1,".");
  548.             } else {
  549.                 strcpy(cp1,"");
  550.             }
  551.             sprintf(tmp,"%s%s%s",sname,cp1,Dsuffix);
  552.             xfree(sname);
  553.             return tmp;
  554.         } else {
  555.             return sname;
  556.         }
  557.     }
  558.     xfree(sname);
  559.     return NULLCHAR;
  560. }
  561.  
  562. #ifdef XXX
  563. /* process outgoing zoneinit */
  564. static void
  565. proc_bootp(int s,void *d,void *b)
  566. {
  567.     int count, len, answers = 5;
  568.     char *buf;
  569.     struct sockaddr_in server;
  570.     struct rr *rrp;
  571.     struct quest *qp;
  572.     struct rr_memory *memory;
  573.     FILE *fp;
  574.     struct mbuf *bp;
  575.     struct Server *dp = (struct Server *) d;
  576.     struct dhdr *dhdr = (struct dhdr *) b;
  577.  
  578.     if(dhdr->qdcount != 1) {
  579.         free_dhdr(dhdr);
  580.         xfree(dp);
  581.         return;
  582.     }
  583.     qp = dhdr->qlist[0];                     /* expecting only 1 question */
  584.  
  585.     if(qp->qtype ==  TYPE_ANY) {
  586.         int auth = DOM_AUTHORITY | DOM_CANRECURSE;
  587.         char *name = strxdup(qp->qname);
  588.         int i = strxlen(name);
  589.  
  590.         if(name[--i] == '.') {
  591.             name[i] = '\0';                 /* undo effect of dn_compress */
  592.         }
  593.         dhdr->rcode = NO_ERROR;
  594.         dhdr->aa = auth;
  595.         dhdr->qr = RESPONSE;
  596.         dhdr->opcode = QUERY;                 /* change opcode for answers */
  597.  
  598.         if((fp = Fopen(name,READ_TEXT,0,0)) == NULLFILE) {
  599.             xfree(name);
  600.             free_dhdr(dhdr);
  601.             xfree(dp);
  602.             return;
  603.         }
  604.         memory = mxallocw(sizeof(struct rr_memory));
  605.         dhdr->ans = cxallocw(answers,sizeof(struct rr *));
  606.         server.sin_family = AF_INET;
  607.         server.sin_port = dp->protocol;
  608.         server.sin_addr.s_addr = dp->address;
  609.         count = 0;
  610.         buf = mxallocw(512);
  611.  
  612.         while((rrp = get_rr(fp,memory)) != NULLRR) {
  613.             dhdr->ans[count++] = rrp;
  614.             if(count == answers) {
  615.                 dhdr->ancount = answers;
  616.                 len = res_mkbuf(dhdr,buf,512);
  617.                 bp = qdata(buf,(int16)len);
  618.                 send_mbuf(s,bp,0,(char *)&server,SOCKSIZE);
  619.  
  620.                 for(i = 0; i < answers; i++) {
  621.                     free_rr(dhdr->ans[i]);
  622.                     dhdr->ans[i] = NULLRR;
  623.                 }
  624.                 count = 0;
  625.                 alarm(Dtimeout * 1000);
  626.  
  627.                 /* Wait for something to happen */
  628.                 pwait(&s);
  629.                 alarm(0L);
  630.             }
  631.         }
  632.         dhdr->ancount = count;
  633.         len = res_mkbuf(dhdr,buf,512);
  634.         free_dhdr(dhdr);
  635.         bp = qdata(buf,(int16)len);
  636.         send_mbuf(s,bp,0,(char *)&server,SOCKSIZE);
  637.         xfree(buf);
  638.         xfree(dp);
  639.         xfree(name);
  640.         Fclose(fp);
  641.     }
  642. }
  643. #endif
  644.  
  645. #ifdef DNS
  646. /* process incoming queries */
  647. void
  648. proc_query(int s,void *d,void *b)
  649. {
  650.     int i, len;
  651.     char *buf;
  652.     struct sockaddr_in server;
  653.     struct rr *rrp, *rrans, *rrns, *rradd, *rrtmp;
  654.     struct mbuf *bp;
  655.  
  656.     struct Server *dp = (struct Server *) d;
  657.     struct dhdr *dhdr = (struct dhdr *) b;
  658.  
  659.     rrans = rrns = rradd = NULLRR;
  660.  
  661.     for(i = 0; i < dhdr->qdcount; i++) {
  662.         struct quest *qp = dhdr->qlist[i];
  663.  
  664.         /* A server is testing here. ASSUMING INTERNET STYLE */
  665.         int auth = (Dhaveaa) ? (DOM_AUTHORITY | DOM_CANRECURSE) : DOM_CANRECURSE;
  666. #ifdef XXX
  667.         int auth = (haveaa(qp->qname)) ? (DOM_AUTHORITY | DOM_CANRECURSE) : DOM_CANRECURSE;
  668. #endif
  669.         dhdr->aa = auth;
  670.         dhdr->qr = RESPONSE;
  671.  
  672.         switch(qp->qtype) {
  673.         case TYPE_A:
  674.             if((rrp = rresolve(qp->qname,TYPE_A,DOM_CANRECURSE)) != NULLRR) {
  675.                 /* we found an entry, go tell him */
  676.                 dhdr->rcode = NO_ERROR;
  677.             } else {
  678.                 /* we did not find an entry, go tell him */
  679.                 rrp = mxallocw(sizeof(struct rr));
  680.                 rrp->name = strxdup(qp->qname);
  681.                 rrp->type = qp->qtype;
  682.                 rrp->class = qp->qclass;
  683.                 rrp->ttl = 500L;
  684.                 rrp->rdata.addr = 0L;
  685.                 rrp->rdlength = 4;    /* size of addr data */
  686.                 dhdr->rcode = NAME_ERROR;
  687.             }
  688.             rrans = rrp;
  689.             break;
  690.         case TYPE_MB:
  691.         case TYPE_MG:
  692.         case TYPE_MR:
  693.         case TYPE_MX:
  694.         case TYPE_NS:
  695.         case TYPE_SOA:
  696.         case TYPE_PTR:
  697.         case TYPE_TXT:
  698.         case TYPE_CNAME:
  699.         case TYPE_HINFO:
  700.         case TYPE_ANY:
  701.             if((rrp = rresolve(qp->qname,qp->qtype,DOM_CANRECURSE)) != NULLRR) {
  702.                 dhdr->rcode = NO_ERROR;
  703.             } else {
  704.                 dhdr->rcode = NAME_ERROR;
  705.             }
  706.             rrans = rrp;
  707.             break;
  708.         /* if I cannot give a reasonable answer , dont give it ... */
  709.         case TYPE_MD:        /* unsupported */
  710.         case TYPE_MF:        /* unsupported */
  711.         case TYPE_WKS:        /* unsupported */
  712.         case TYPE_NULL:        /* unsupported */
  713.         case TYPE_MINFO:    /* unsupported */
  714.         default:
  715.             dhdr->rcode = NOT_IMPL;
  716.         }
  717.     }
  718.     i = 0;
  719.     rrtmp = rrans;
  720.  
  721.     while(rrtmp != NULLRR) {
  722.         i++;
  723.         rrtmp = rrtmp->next;
  724.     }
  725.     if((dhdr->ancount = i) > 0) {
  726.         dhdr->ans = cxallocw(i,sizeof(struct rr *));
  727.  
  728.         rrtmp = rrans;
  729.         i = 0;
  730.  
  731.         while(rrtmp != NULLRR) {
  732.             dhdr->ans[i] = rrtmp;
  733.             i++;
  734.             rrans = rrtmp;
  735.             rrtmp = rrtmp->next;
  736.             rrans->next = NULLRR; /* break link */
  737.         }
  738.     }
  739.     i = 0;
  740.     rrtmp = rrns;
  741.  
  742.     while(rrtmp != NULLRR) {
  743.         i++;
  744.         rrtmp = rrtmp->next;
  745.     }
  746.     if((dhdr->nscount = i) > 0) {
  747.         dhdr->ns = cxallocw(i,sizeof(struct rr *));
  748.  
  749.         rrtmp = rrns;
  750.         i = 0;
  751.  
  752.         while(rrtmp != NULLRR) {
  753.             dhdr->ns[i] = rrtmp;
  754.             i++;
  755.             rrns = rrtmp;
  756.             rrtmp = rrtmp->next;
  757.             rrns->next = NULLRR; /* break link */
  758.         }
  759.     }
  760.     i = 0;
  761.     rrtmp = rradd;
  762.  
  763.     while(rrtmp != NULLRR) {
  764.         i++;
  765.         rrtmp = rrtmp->next;
  766.     }
  767.     if((dhdr->arcount = i) > 0) {
  768.         dhdr->add = cxallocw(i,sizeof(struct rr *));
  769.  
  770.         rrtmp = rradd;
  771.         i = 0;
  772.  
  773.         while(rrtmp != NULLRR) {
  774.             dhdr->add[i] = rrtmp;
  775.             i++;
  776.             rradd = rrtmp;
  777.             rrtmp = rrtmp->next;
  778.             rradd->next = NULLRR; /* break link */
  779.         }
  780.     }
  781.     buf = mxallocw(512);
  782.     len = res_mkbuf(dhdr,buf,512);
  783.     free_dhdr(dhdr);
  784.     server.sin_family = AF_INET;
  785.     server.sin_port = dp->protocol;
  786.     server.sin_addr.s_addr = dp->address;
  787.     bp = qdata(buf,(int16)len);
  788.     send_mbuf(s,bp,0,(char *)&server,SOCKSIZE);
  789.     xfree(buf);
  790.     xfree(dp);
  791. }
  792. #endif
  793.  
  794.